<?php
/**
 * @author jonathan <jo.link.noir@gmail.com>
 * @version 1.0: jo_link_noir
 * @date 14-04-2010
 */
class U1_Move_Attack extends SW_Move
{
	/** @var string*/
	protected $orderName = 'attack';

	/** @var SW_Removable*/
	protected $resource = null;


	/**
	 * @param int $endPoint
	 * @param int $time = null
	 */
	public function __construct($endPoint, $time = null)
	{
		parent::__construct($endPoint, null, $time);
	}

	/**
	 * @param U1_Units $army
	 * @param U1_Planet $planet
	 */
	protected function initResourcePilier(U1_Units $units, U1_Planet $planet)
	{
		$freight = $units->getStat(U1_Unit::STAT_FREIGHT);
		$resource = $planet->getInstance(U1_Resource::INDEX, $this->endPoint);
		$resourceQuantity = $resource->getQuantities($this->time);
		$protectedResources = $planet->getInstance(U1_Building::INDEX, $this->endPoint)
			->getProtectedResources();

		$pilier = array();
		foreach ($resourceQuantity as $k => $v)
		{
			$v -= $protectedResources[$k];
			if (0 >= $v)
				unset($resourceQuantity[$k]);
			else
				$pilier[$k] = 0;
		}

		//calcul des ressources volées
		//diviseur de ressource (quantité à stocké)
		$div = count($resourceQuantity);
		while ($div && 0 < $freight)
		{
			$getResource = $freight / $div;
			foreach ($resourceQuantity as $k => &$quantity)
			{
				if (0 >= $quantity)
				{
					unset($resourceQuantity[$k]);
					--$div;
				}
				else if ($getResource < $quantity)
				{
					$freight -= $getResource;
					$pilier[$k] += $getResource;
					$quantity -= $getResource;
				}
				else
				{
					$freight -= $quantity;
					$pilier[$k] += $quantity;
					unset($resourceQuantity[$k]);
					--$div;
				}
			}
		}

		foreach ($pilier as $k => &$v)
		{
			if (0 >= $v)
				unset($pilier[$k]);
			else
				$v = (int)$v;
		}

		if (!empty($pilier))
		{
			$resource->decrease($pilier, $this->time);
			$this->resource = new U1_Removable_Resource($pilier);
		}
	}

	/**
	 * Récupère et finit la construction de la structure (finishCompletedLists) de la planète désigné par $point
	 * @param U1_Planet $planet
	 * @param mixed $nameStruct
	 * @param int point
	 * @return SW_Structure
	 */
	protected function getStructureAndFinishCompletLists(U1_Planet $planet, $nameStruct, $point)
	{
		$struct = $planet->getInstance($nameStruct, $point);
		$struct->finishCompletedLists($this->time);
		return $struct;
	}

	/**
	 * @param string $message
	 * @param bool $sendMessagePlayerTarget = true : si false aucun message n'est envoyer à la planète attaquer
	 */
	protected function sendMessage($message, $sendMessagePlayerTarget = true)
	{
		$date = new DateTime('@'.$this->time, new DateTimeZone('Europe/Paris'));

		if ($sendMessagePlayerTarget)
			U1_DAO_Message::send($this->player_target, $message, U1_Display_Move::getSujetMove($this->orderName, true), false, $date);
		U1_DAO_Message::send($this->player_sends, $message, U1_Display_Move::getSujetMove($this->orderName, false), false, $date);
	}

	/**
	 * Méthode à déclencher quand l'armé est arrivé à destination
	 * @param SW_Units $army
	 * TODO méthode d'envoie de message dans la classe (déplacé celui dans U1_Display_Move)
	 */
	public function arrive(SW_Units $units)
	{
		if (($planetEnd = U1_Planet::factoryContainsPlanetId($this->endPoint))
		 && $planetEnd->get($this->endPoint)->getRefUser()
		 && $this->process($units, $planetEnd))
			U1_DAO_Move::deleteId($this->id);
		else
			U1_DAO_Move::baseSend($units, $this, $this->resource);
	}

	/**
	 * Méthode appelé pour effectué une action sur une planète habité
	 * @param SW_Units $units
	 * @param U1_Planet $planetEnd
	 * @return bool : true si la flotte doit être détruite. false si la flotte doit revenir.
	 */
	protected function process(SW_Units $units, U1_Planet $planetEnd)
	{
		//récupère l'objet des armes et termine les constructions
		$armyEnd = $this->getStructureAndFinishCompletLists($planetEnd, U1_Army::INDEX, $this->endPoint);
		$unitsEnd = $armyEnd->getUnits(true);

		//si c'est vide, c'est une victoire
		if ($unitsEnd->isEmpty())
		{
			//pillage de ressources
			$this->initResourcePilier($units, $planetEnd);

			$this->sendMessage(U1_Display_Move::getReportAttack(U1_DAO_Planet::selectId($this->startPoint), $planetEnd->get($this->endPoint), U1_Display_Army::getMessageConfrontationResult(false, true), $this->resource));
		}
		else
		{
			//récupère l'objet des recherches et termine les constructions
			$researchEnd = $this->getStructureAndFinishCompletLists($planetEnd, U1_Research::INDEX, $this->endPoint);
			//initialisent les unités
			$armyEnd->initStats($unitsEnd, $researchEnd);

			$countsUnitsEnd = $unitsEnd->toArray();
			$report = U1_Confrontation::confrontation($units, $unitsEnd);

			//$countsUnitsEnd va contenir les pertes
			$countsUnitsEndAfter = $unitsEnd->toArray();
			foreach ($countsUnitsEnd as $k => &$v)
			{
				if (isset($countsUnitsEndAfter[$k]))
				{
					if ($countsUnitsEndAfter[$k] == $v)
						unset($countsUnitsEnd[$k]);
					else
						$v -= $countsUnitsEndAfter[$k];
				}
			}

			//actualisé la bdd. Les objets Army_Element seront automatiquement actualisés
			U1_Army_DAO::getFactory()->decrease($this->endPoint, $countsUnitsEnd);

			if ($units->isEmpty())
				$baseSend = true;
			else
			{
				if ($unitsEnd->isEmpty())
					//pillage de ressources
					$this->initResourcePilier($units, $planetEnd);
				$baseSend = false;
			}

			$this->sendMessage(U1_Display_Move::getReportAttack(U1_DAO_Planet::selectId($this->startPoint), $planetEnd->get($this->endPoint), $report, $this->resource));
			return $baseSend;
		}
	}
}